#ifndef __ASIO_TCP_CONNECTOR_IMPL_H__
#define __ASIO_TCP_CONNECTOR_IMPL_H__

#include "tcp_message_context.h"
#include "tcp_session.h"

#include <string>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include "../io_handler.h"


namespace vpm 
{
	namespace mina
	{
		namespace detail
		{
			using namespace boost::asio::ip;

			template <class Session= TcpSession,class SessionConfigPtr = TcpSessionConfigPtr> 
			class AsioTcpConnectorImpl 
			{
			public:

				AsioTcpConnectorImpl(TcpConnectorConfigPtr config ,IoHandler& handler)
					:m_connectorConfig(config),
					m_tcpSocket(m_ioService),
					m_ioHandler(handler),
					m_tcpSession(m_tcpSessionConfig)
				{
				}

				~AsioTcpConnectorImpl()
				{
					
				}
//
//				int server_port()
//				{
//					return m_serverPort; 
//				}
//
//				const std::string server_host()
//				{
//					return m_serverHost;
//				}

				int connect(int port, const std::string & host= "0.0.0.0")
				{
					if (!m_tcpSocket.is_open())
					{
						m_peerPoint = tcp::endpoint(boost::asio::ip::address::from_string(host),port);
						m_tcpSocket.async_connect(m_peerPoint,boost::bind(&AsioTcpConnectorImpl::handle_connect,this,
							boost::asio::placeholders::error));

						boost::thread srvThread(boost::bind(&boost::asio::io_service::run, &m_ioService));
					}
					return 0; 
				}

				int close_connection()
				{
					m_tcpSocket.close();
					return 0;
				}

				void handle_connect(const boost::system::error_code &err)
				{
					if (!err)
					{
						

						IoSessionAccessor::attach_writter(m_tcpSession,boost::bind(&AsioTcpConnectorImpl::send_data,this,_1));
						IoSessionAccessor::attach_reader(m_tcpSession,boost::bind(&AsioTcpConnectorImpl::recv_data,this,_1));
						IoSessionAccessor::attach_closer(m_tcpSession,boost::bind(&AsioTcpConnectorImpl::close_connection,this));


						m_tcpSocket.async_read_some(boost::asio::buffer(m_dataBuf),
							boost::bind(&AsioTcpConnectorImpl::handle_read,this,
							boost::asio::placeholders::error,
							boost::asio::placeholders::bytes_transferred) );
						m_ioHandler.session_opened(m_tcpSession);
					}
				}

				void handle_read(const boost::system::error_code& error,std::size_t bytes_transferred)
				{
					if (!error)
					{
						printf("received data,length  %d\n",bytes_transferred);

						TcpMessageContext context(m_dataBuf,(int)bytes_transferred); 
						m_ioHandler.message_received(m_tcpSession,context);

						m_tcpSocket.async_read_some(boost::asio::buffer(m_dataBuf),
							boost::bind(&AsioTcpConnectorImpl::handle_read,this,
							boost::asio::placeholders::error,
							boost::asio::placeholders::bytes_transferred) );

					}
					else 
					{

					}

				}

				int disconnect()
				{
					return 0; 
				}	

				int send_data(MessageContext & msg)
				{
					TcpMessageContext & tcpMsg = (TcpMessageContext&)msg; 
					return this->send_data(tcpMsg.read(),tcpMsg.readable());		
				}

				int send_data(const char * pData, int dataLen)
				{					
					boost::asio::async_write(m_tcpSocket, boost::asio::buffer(pData,dataLen),
						boost::bind(&AsioTcpConnectorImpl<Session,SessionConfigPtr>::handle_write_request, this,
						boost::asio::placeholders::error));

					return 0; 
				}

				int recv_data(MessageContext & msg)
				{
					 return 0; 
				}

				void handle_write_request(boost::system::error_code err)
				{

				}

				virtual int recv_data(char * pBuf, int bufLen)
				{
					return 0; 
				}

			private:
				TcpConnectorConfigPtr m_connectorConfig; 				
				IoHandler & m_ioHandler; 	
		 
				char m_dataBuf[1024*8]; 
				boost::asio::io_service m_ioService; 
				tcp::socket m_tcpSocket;
				tcp::endpoint m_peerPoint; 
				TcpSessionConfig m_tcpSessionConfig;
			 

				Session m_tcpSession; //connector has only one session
			};
		}
	}
}
#define TcpConnectorImpl  AsioTcpConnectorImpl


#endif // __ASIO_TCP_CONNECTOR_IMPL_H__
